package one.stand.service.impl;

import com.alibaba.fastjson.JSON;
import com.github.vioao.wechat.api.component.ComponentApi;
import com.github.vioao.wechat.bean.response.BaseResponse;
import com.github.vioao.wechat.bean.response.component.*;
import com.github.vioao.wechat.bean.response.component.wxa.template.LibraryAddResponse;
import one.stand.code.RedisCode;
import one.stand.enums.EnumUtil;
import one.stand.enums.LoginEnum;
import one.stand.enums.WxNoticeEnums;
import one.stand.model.*;
import one.stand.request.CompanyAccountRequest;
import one.stand.service.CodeService;
import one.stand.service.ComponentService;
import one.stand.service.DomainService;
import one.stand.service.TemplateService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * @author: QIK
 * @CreateDate: 2019/5/9 10:22
 */
@Service
public class ComponentServiceImpl extends PublicBaseService implements ComponentService {
    private ComponentApi componentApi = new ComponentApi();
    @Lazy
    @Autowired
    private DomainService domainService;
    @Lazy
    @Autowired
    private CodeService codeService;
    @Override
    public String getComponentToken() {
        String ticket = redisUtil.get(RedisCode.getTicket(componentConfig.getAppid()));
        String key = RedisCode.getComponentTokenKey(componentConfig.getAppid());
        String token = redisUtil.get(key);
        if (null == token) {
            GetComponentTokenResponse getComponentTokenResponse = componentApi.getComponentToken(componentConfig.getAppid(), componentConfig.getSecret(), ticket);
            if (getComponentTokenResponse.isSuccess()) {
                token = getComponentTokenResponse.getComponentAccessToken();
                redisUtil.set(key, token, 100, TimeUnit.MINUTES);
            }
            log.info("componentToken:{}", JSON.toJSONString(getComponentTokenResponse));
        }
        return token;
    }


    @Override
    public String createPreAuthCode() {
        String code=null;
            CreatePreAuthCodeResponse createPreAuthCodeResponse = componentApi.createPreAuthCode(getComponentToken(), componentConfig.getAppid());
            if (createPreAuthCodeResponse.isSuccess()) {
                code = createPreAuthCodeResponse.getPreAuthCode();
            }
        return code;
    }

    @Override
    public ResultModel<String> componentloginpage(CompanyAccountRequest request) {
        if (StringUtils.isEmpty(request.getAppId()) || null == request.getAccountType()||StringUtils.isEmpty(request.getAppSecret())||StringUtils.isEmpty(request.getAppName())) {
            return ResultModel.checkParamFail();
        }
        CompanyAccountModel model = companyAccountMapper.select(new CompanyAccountModel() {{
            setCompanyId(request.getCId().intValue());
            setAccountType(request.getAccountType());
        }});
        log.info("获取授权码：{}", JSON.toJSONString(model));
        if (null != model) {
            if (model.getState() == 1) {
                return ResultModel.fail("您以及认证成功，无需再次认证");
            }
            model.setAppId(request.getAppId());
            model.setAppSecret(request.getAppSecret());
            companyAccountMapper.updateByPrimaryKeySelective(model);
        }
        if (model == null) {
            CompanyModel companyModel=companyMapper.selectByPrimaryKey(request.getCId().intValue());
            model = new CompanyAccountModel();
            model.setAppId(request.getAppId());
            model.setAccountType(request.getAccountType());
            model.setCreateTime(currentDate());
            model.setCompanyId(request.getCId().intValue());
            model.setCompanyKey(companyModel.getCompanyKey());
            model.setAppName(request.getAppName());
            model.setAppSecret(request.getAppSecret());
            companyAccountMapper.insertSelective(model);
        }
        StringBuffer stringBuffer = new StringBuffer(componentApi.getComponentLoginPage(componentConfig.getAppid(), createPreAuthCode(), componentConfig.getRedirectUri(), "3", request.getAppId()));
        stringBuffer.append("&type=").append(request.getAccountType());
        return ResultModel.success(stringBuffer.toString());
    }

    @Override
    public QueryAuthResponse queryAuth(String code) {
        QueryAuthResponse respons = componentApi.queryAuth(getComponentToken(), componentConfig.getAppid(), code);
        return respons;
    }

    @Override
    public ResultModel getAuthorizerInfo(CompanyAccountRequest request) {
        if(StringUtils.isEmpty(request.getAppId())){
            return ResultModel.checkParamFail();
        }
        String key = RedisCode.getAuthorizerRefreshTokenKey(request.getAppId());
        String token=getComponentToken();
        GetAuthorizerInfoResponse response = componentApi.getAuthorizerInfo(token, componentConfig.getAppid(), request.getAppId());
        QueryAuthResponse info=response.getAuthorizationInfo();
        if (response.isSuccess()) {
            token = response.getAuthorizationInfo().getAuthorizerAccessToken();
            if (StringUtils.isEmpty(token)) {
                token = response.getAuthorizationInfo().getAuthorizerRefreshToken();
            }
            redisUtil.set(key, token);

        }
        info.setAppid(null);
        info.setAuthorizerAccessToken(null);
        info.setAuthorizerRefreshToken(null);
        response.setAuthorizationInfo(info);
        return ResultModel.success(response);
    }

    @Override
    public String getAuthorizerRefreshToken(String appid) {
        String key = RedisCode.getAuthorizerRefreshTokenKey(appid);
        String token = redisUtil.get(key);
        if (StringUtils.isEmpty(token)) {
            GetAuthorizerInfoResponse response = componentApi.getAuthorizerInfo(getComponentToken(), componentConfig.getAppid(), appid);
            if (response.isSuccess()) {
                token = response.getAuthorizationInfo().getAuthorizerAccessToken();
                if (StringUtils.isEmpty(token)) {
                    token = response.getAuthorizationInfo().getAuthorizerRefreshToken();
                }
                redisUtil.set(key, token,10,TimeUnit.MINUTES);

            }
            log.info("获取代小程序账号信息：{}", JSON.toJSONString(response));
        }
        return token;
    }

    @Override
    public String getAuthorizerToken(String appid) {
        String token=redisUtil.get(RedisCode.getAuthorizerToken(appid));
        if(StringUtils.isEmpty(token)){
            GetAuthorizerTokenResponse getAuthorizerTokenResponse = componentApi.getAuthorizerToken(getComponentToken(), componentConfig.getAppid(), appid, getAuthorizerRefreshToken(appid));
            if (getAuthorizerTokenResponse.isSuccess()) {
                token = getAuthorizerTokenResponse.getAuthorizerAccessToken();
                redisUtil.set(RedisCode.getAuthorizerToken(appid),token,100,TimeUnit.MINUTES);
            }
        }
        return token;
    }

    @Override
    public ResultModel componentCallBack(CompanyAccountRequest request) {
        if (StringUtils.isEmpty(request.getAuthCode()) || StringUtils.isEmpty(request.getAppId())) {
            return ResultModel.checkParamFail();
        }
        QueryAuthResponse response = queryAuth(request.getAuthCode());
        log.info("授权成功后返回数据：{}", JSON.toJSONString(response));
        if(!response.getErrcode().equals(0)){
            return ResultModel.fail();
        }
        String token = getAuthorizerToken(request.getAppId());
        log.info("获取代理小程序Token:{}", token);
        CompanyAccountModel model = companyAccountMapper.select(new CompanyAccountModel() {{
            setAppId(request.getAppId());
        }});
        if (null != model) {
            model.setState(1);
            companyAccountMapper.updateByPrimaryKeySelective(model);
        }else {
            log.info("授权回调，未查到账号信息。。。。。。。。。。。。。");
            return ResultModel.fail("未查到账号信息");
        }
        BaseResponse baseResponse= domainService.modifyDomain(request.getAppId());
        log.info("授权后设置白名单：{}",baseResponse.toString());
        addTemplate(model);

        //验证是否绑定完两个小程序
        List<CompanyAccountModel>  accountModelList=companyAccountMapper.selectProgramByCompanyId(new CompanyAccountModel(){{
            setCompanyId(model.getCompanyId().intValue());
        }});
        if(null==accountModelList||accountModelList.size()!=2){
            log.info("小程序账号不齐全不进行发布操作");
        }else{
           for(CompanyAccountModel cam:accountModelList){
               commit(cam.getAppId(),cam.getAccountType());
           }
            log.info("进行发布小程序");
        }
        return ResultModel.success();
    }

    @Async("asyncServiceExecutor")
    public void commit(String appId,Integer type){
        VersionModel versionModel=versionMapper.select(new VersionModel(){{
            setVersionState(1);
            setVersionType(type);
        }});
        if(null!=versionModel){
            log.info("开始代码提交");
            codeService.commit(appId,versionModel.getVersionId(),true);
        }
    }

    /**
     *
     */
    @Autowired
    protected TemplateService templateService;

    @Async("asyncServiceExecutor")
    public void addTemplate(CompanyAccountModel model){
        log.info("小程序微信模板添加：",model.toString());
        WxNoticeEnums[] wxNoticeEnums = WxNoticeEnums.values();
        LoginEnum loginEnum=EnumUtil.getByIntegerTypeCode(LoginEnum.class,"getAccountType",model.getAccountType().toString());
        for(WxNoticeEnums enums : wxNoticeEnums){
            if(enums.getType().equals(loginEnum.getCode().toUpperCase())){
                LibraryAddResponse libraryAddResponse = templateService.libraryAdd(model.getAppId(), enums.getNoticeId(), enums.getData());
                WxNoticeModel wxNoticeModel = new WxNoticeModel();
                wxNoticeModel.setCompanyId(model.getCompanyId());
                wxNoticeModel.setWxNoticeName(enums.getName());
                wxNoticeModel.setCode(enums.getCode());
                wxNoticeModel.setValue(libraryAddResponse.getTemplateId());
                wxNoticeModel.setType(enums.getType());
                wxNoticeModel.setPage(enums.getPage());
                wxNoticeModel.setCreateTime(currentDate());
                wxNoticeMapper.insertSelective(wxNoticeModel);
            }

        }
    }
}

